#pragma once

#include <gl\gl.h>	// Header File For The OpenGL32 Library
//#include <GL\GL.h>
#include <GL\GLU.h>
//#include <GL\GLUT.h>

#pragma comment (lib, "OpenGL32.lib")
#pragma comment (lib, "GLu32.lib")
//#pragma comment (lib, "Glaux.lib")


//#include "math.h"
//Math types derived from the KempoApi tMath library
typedef union Tuple2d_t
{
    struct
    {
        GLdouble X, Y;
    } s;

    GLdouble T[2];
} Point2dT, Vector2dT;//Tuple2dT;      //A generic 2-element tuple that is represented by single-precision floating point x,y coordinates. 

typedef union Tuple3d_t
{
    struct
    {
        GLdouble X, Y, Z;
    } s;

    GLdouble T[3];
} Vector3dT;//Tuple3dT;      //A generic 3-element tuple that is represented by single precision-floating point x,y,z coordinates. 

typedef union Tuple4d_t
{
    struct
    {
        GLdouble X, Y, Z, W;
    } s;

    GLdouble T[4];
} Quat4dT;//Tuple4dT;      //A 4-element tuple represented by single-precision floating point x,y,z,w coordinates. 

typedef union Matrix3d_t
{
        struct
        {
            //column major
            union { GLdouble M00; GLdouble XX; GLdouble SX; };  //XAxis.X and Scale X
            union { GLdouble M10; GLdouble XY;             };  //XAxis.Y
            union { GLdouble M20; GLdouble XZ;             };  //XAxis.Z
            union { GLdouble M01; GLdouble YX;             };  //YAxis.X
            union { GLdouble M11; GLdouble YY; GLdouble SY; };  //YAxis.Y and Scale Y
            union { GLdouble M21; GLdouble YZ;             };  //YAxis.Z
            union { GLdouble M02; GLdouble ZX;             };  //ZAxis.X
            union { GLdouble M12; GLdouble ZY;             };  //ZAxis.Y
            union { GLdouble M22; GLdouble ZZ; GLdouble SZ; };  //ZAxis.Z and Scale Z
        } s;
        GLdouble M[9];
} Matrix3dT;     //A single precision floating point 3 by 3 matrix. 

typedef union Matrix4d_t
{
        struct
        {
            //column major
            union { GLdouble M00; GLdouble XX; GLdouble SX; };  //XAxis.X and Scale X
            union { GLdouble M10; GLdouble XY;             };  //XAxis.Y
            union { GLdouble M20; GLdouble XZ;             };  //XAxis.Z
            union { GLdouble M30; GLdouble XW;             };  //XAxis.W
            union { GLdouble M01; GLdouble YX;             };  //YAxis.X
            union { GLdouble M11; GLdouble YY; GLdouble SY; };  //YAxis.Y and Scale Y
            union { GLdouble M21; GLdouble YZ;             };  //YAxis.Z
            union { GLdouble M31; GLdouble YW;             };  //YAxis.W
            union { GLdouble M02; GLdouble ZX;             };  //ZAxis.X
            union { GLdouble M12; GLdouble ZY;             };  //ZAxis.Y
            union { GLdouble M22; GLdouble ZZ; GLdouble SZ; };  //ZAxis.Z and Scale Z
            union { GLdouble M32; GLdouble ZW;             };  //ZAxis.W
            union { GLdouble M03; GLdouble TX;             };  //Trans.X
            union { GLdouble M13; GLdouble TY;             };  //Trans.Y
            union { GLdouble M23; GLdouble TZ;             };  //Trans.Z
            union { GLdouble M33; GLdouble TW; GLdouble SW; };  //Trans.W and Scale W
        } s;
        GLdouble M[16];
} Matrix4dT;     //A single precision floating point 4 by 4 matrix. 


typedef union Color4d_t
{
        struct
        {
			GLdouble R;
			GLdouble G;
			GLdouble B;
			GLdouble A;
        } s;
        GLdouble C[4];
} Color4dT;     //A single precision floating point 4 by 4 matrix. 

typedef union Color3d_t
{
        struct
        {
			GLdouble R;
			GLdouble G;
			GLdouble B;
        } s;
        GLdouble C[3];
} Color3dT;     //A single precision floating point 4 by 4 matrix. 
	//GLdouble GetScale/*Matrix4dSVD*/(const Matrix4dT* NewObj/*, Matrix4dT* rot4*/)
	//{
	//	  GLdouble s;//, n;


 //   // this is a simple svd.
 //   // Not complete but fast and reasonable.
 //   // See comment in Matrix3d.

	//	  s = sqrt (
 //           ( (NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ) + 
 //             (NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ) +
 //             (NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ) ) / 3.0 );

 //  
 //   //if (rot4)   //if pointer not null
 //   //{
 //   //    if (rot4 != NewObj)
 //   //    {
 //   //        Matrix4dSetRotationScaleFromMatrix4d(rot4, NewObj);  // private method
 //   //    }

 //   //    // zero-div may occur.

 //   //    n = 1.0 / sqrt( (NewObj->s.XX * NewObj->s.XX) +
 //   //                              (NewObj->s.XY * NewObj->s.XY) +
 //   //                              (NewObj->s.XZ * NewObj->s.XZ) );
 //   //    rot4->s.XX *= n;
 //   //    rot4->s.XY *= n;
 //   //    rot4->s.XZ *= n;

 //   //    n = 1.0 / sqrt( (NewObj->s.YX * NewObj->s.YX) +
 //   //                              (NewObj->s.YY * NewObj->s.YY) +
 //   //                              (NewObj->s.YZ * NewObj->s.YZ) );
 //   //    rot4->s.YX *= n;
 //   //    rot4->s.YY *= n;
 //   //    rot4->s.YZ *= n;

 //   //    n = 1.0 / sqrt( (NewObj->s.ZX * NewObj->s.ZX) +
 //   //                              (NewObj->s.ZY * NewObj->s.ZY) +
 //   //                              (NewObj->s.ZZ * NewObj->s.ZZ) );
 //   //    rot4->s.ZX *= n;
 //   //    rot4->s.ZY *= n;
 //   //    rot4->s.ZZ *= n;
 //   //}

 //   return s;
	//}